/*
 *  (c) 2010-2012 Ashwin Rayaprolu (http://linkwithweb.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
 *  file except in compliance with the License. You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the
 *  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 *  either express or implied. See the License for the specific language governing permissions
 *  and limitations under the License.
 */
 
/**
 * Create Component factory as anonymous function and initialize the variable It
 * stores all component instances from which we make copies...
 */
var SwiftUIComponentFactory = (function() {
    var componentRegistry = {}; // private
    return { // exposed to public
        registerComponent: function(name,uiComponent) {
        	if(componentRegistry[name] == undefined || !componentRegistry[name])
        		componentRegistry[name]={componentName:name,component:uiComponent};
        },
        getComponent: function(name){
        	// Clone the component and return
        	return SwiftUI.extend({}, componentRegistry[name]);
        }
    }
}());


/**
 * Top level Abstract class for All design Components. All components have to
 * extend this
 */
SwiftUI.UIDesignComponent = function(options) {
	this.initialize(options);
};

SwiftUI.UIDesignComponent.prototype = {
		
/**
 * @class Implements drag-n-drop manager -- a group of linked draggables and
 *        drop zones
 * @constructs
 */
   initialize: function(options) {
      this.designContainer = null;
      this.componentElement = null;
      
      /**
		 * Assign default data loading services url
		 */
      this.options={  
          text  : "",
          name  : "",
          id    : "",
          icon  : "",
          htmlElementText : "",
          componentType : "",
          
          colSpan : 1,
          rowSpan : 1,
          
          isContainer : false,
          // To store components present location on the container.
          xCoordinate : -1,
          yCoordinate : -1
    	  
      };
      
      SwiftUI.extend(this.options, options || {});
      /**
		 * Register with componentfactory for future reuse
		 */
      SwiftUIComponentFactory.registerComponent(this.options.componentType,this);
      
   },
   
	setColSpan:function(value){
		this.options.colSpan = value;
	},
	
	setRowSpan:function(value){
		this.options.colSpan = value;
	},
	
	setXCoordinate:function(value){
		this.options.xCoordinate = value;
	},
	
	setYCoordinate:function(value){
		this.options.yCoordinate = value;
	},
	
	setDesignContainer: function(container){
		this.designContainer = container;
	},
	
	getColSpan:function(){
		return this.options.colSpan;
	},
	
   
   /**
	 * 
	 */
   enableDrag: function (dragContainment,draggableClass,resizable){
       // Make element draggable and resizable
		$(draggableClass).click(
			function(event) {
				if (event.ctrlKey) {
					$(this).toggleClass('grouped');
				}				
			}	
		);			

		if(resizable=="true"){
			this.componentElement = $(draggableClass).corner().resizable();
		}else{
			this.componentElement = $(draggableClass).corner();
		}
		

		/**
		 * If this element is a container enable droppable feature so that other
		 * components can be dragged onto this
		 */
		if(this.componentElement.hasClass("containerdiv")){
		
			// Make element droppable
			this.componentElement.droppable({greedy: true,
				out: function(event, ui) { 
					var element=$(ui.draggable);
					if(!element.hasClass("containerdiv")){
						$(this).parent().append(element);	
					}					
				},
				drop: function(ev, ui) {
					if (ui.helper.attr('id').search(/drag[0-9]/) != -1){
						var element=$(ui.draggable);
							counter++;

							element=$(ui.draggable).clone();
							// alert(element);
							element.addClass("tempclass");
							
							$(this).append(element);
							
							$(".tempclass").attr("id","clonediv"+counter);
							$("#clonediv"+counter).removeClass("tempclass");

							// Get the dynamically item id
							draggedNumber = ui.helper.attr('id').search(/drag([0-9])/)
							// itemDragged = "dragged" + RegExp.$1
							// //console.log(itemDragged)
							itemDragged = "dragged";

							$("#clonediv"+counter).addClass(itemDragged);
							
							
						
							enableDrag("frame","#clonediv"+counter,"true");
							 

					}else{
						var element=$(ui.draggable);
						// console.log(element.html());
						$(this).append(element);
					}
				}
			});
		
		}
		
		
		/**
		 * Now make this element draggable
		 */
       element.draggable({
    	   /**
			 * We are cloning the present element as we want to clone the
			 * component before displaying on container
			 */
           helper:'clone',
           containment: dragContainment,

			start : function(event, ui) {
				posTopArray = [];
				posLeftArray = [];
				thisElem = $(this);
				
				if ($(this).hasClass("grouped")) { // Loop through each element
													// and store beginning start
													// and left positions
				
					$(".grouped").each(function(i) {
						thiscsstop = $(this).css('top');
						if (thiscsstop == 'auto')
							thiscsstop = 0; // For IE

						thiscssleft = $(this).css('left');
						if (thiscssleft == 'auto')
							thiscssleft = 0; // For IE

						posTopArray[i] = parseInt(thiscsstop);
						posLeftArray[i] = parseInt(thiscssleft);
					});
					}

				begintop = $(this).offset().top; // Dragged element top
													// position
				beginleft = $(this).offset().left; // Dragged element left
													// position
			},	

			drag : function(event, ui) {
				var topdiff = $(this).offset().top - begintop; // Current
																// distance
																// dragged
																// element has
																// traveled
																// vertically
				var leftdiff = $(this).offset().left - beginleft; // Current
																	// distance
																	// dragged
																	// element
																	// has
																	// traveled
																	// horizontally
				
				
				var draggingId = $(this).attr("id");
				if ($(this).hasClass("grouped")) {
					// //console.log("Initial pos "+begintop +"
					// Left----"+beginleft);
					// //console.log("Diff Value is "+topdiff +"
					// Left----"+leftdiff);
					$(".grouped").each(function(i) {
						if(draggingId === $(this).attr("id")){
							topdiff = $(this).offset().top - begintop; // Current
																		// distance
																		// dragged
																		// element
																		// has
																		// traveled
																		// vertically
							leftdiff = $(this).offset().left - beginleft; // Current
																			// distance
																			// dragged
																			// element
																			// has
																			// traveled
																			// horizontally
						}
					});
					
					$(".grouped").each(function(i) {
						// //console.log("Pres pos for "+$(this).attr('id')+" is
						// "+posTopArray[i] +" Left----"+posLeftArray[i]);
						if(draggingId !== $(this).attr("id")){
							$(this).css('top', posTopArray[i] + topdiff); // Move
																			// element
																			// veritically
																			// -
																			// current
																			// css
																			// top
																			// +
																			// distance
																			// dragged
																			// element
																			// has
																			// travelled
																			// vertically
							$(this).css('left', posLeftArray[i] + leftdiff); // Move
																				// element
																				// horizontally
																				// -
																				// current
																				// css
																				// left
																				// +
																				// distance
																				// dragged
																				// element
																				// has
																				// travelled
																				// horizontally
						}
					});					
					
				}
			},
			
           // When first dragged
           stop:function(ev, ui) {
           	var pos=$(ui.helper).offset();
           	objName = "#clonediv"+counter
				var draggingId = $(this).attr("id");
				
				var leftValue = pos.left;
				var topValue = pos.top;
				
				/**
				 * The below if loop is written to fix the relative and
				 * abosiulte positioning issue. When any draggable object is
				 * dropped into a droppable container which resides in another
				 * container then the droppable with more z-index becomes
				 * relative positining for its sub elements
				 */
				if($(this).parent().hasClass("containerdiv")){
					// console.log("Left Pos "+leftValue);
					// console.log("Top Pos "+topValue);
					// console.log("$(this).parent().attr('left')
					// "+$(this).parent().offset().left);
					// console.log("$(this).parent().offset().top
					// "+$(this).parent().offset().top);
					leftValue = pos.left-$(this).parent().offset().left;
					topValue = pos.top -$(this).parent().offset().top;
				}
				
				if ($(this).hasClass("drag")) {
					$(objName).css({"left":leftValue,"top":topValue});
					$(objName).removeClass("drag");					
				
				}else{
					objName = draggingId;
					thisElem.css({"left":leftValue,"top":topValue});
				}
				

				// console.log("Left Pos "+leftValue);
				// console.log("Top Pos "+topValue);
				
				var topdiff = $(this).offset().top - begintop; // Current
																// distance
																// dragged
																// element has
																// traveled
																// vertically
				var leftdiff = $(this).offset().left - beginleft; // Current
																	// distance
																	// dragged
																	// element
																	// has
																	// traveled
																	// horizontally
				
				// This logic for Group Elements
				
				if ($(this).hasClass("grouped")) {
					// //console.log("Initial pos "+begintop +"
					// Left----"+beginleft);
					// //console.log("Diff Value is "+topdiff +"
					// Left----"+leftdiff);
					$(".grouped").each(function(i) {
						if(draggingId === $(this).attr("id")){
							topdiff = $(this).offset().top - begintop; // Current
																		// distance
																		// dragged
																		// element
																		// has
																		// traveled
																		// vertically
							leftdiff = $(this).offset().left - beginleft; // Current
																			// distance
																			// dragged
																			// element
																			// has
																			// traveled
																			// horizontally
						}
					});
					
					$(".grouped").each(function(i) {
						// //console.log("Pres pos for "+$(this).attr('id')+" is
						// "+posTopArray[i] +" Left----"+posLeftArray[i]);
						if(draggingId !== $(this).attr("id")){
							$(this).css('top', posTopArray[i] + topdiff); // Move
																			// element
																			// veritically
																			// -
																			// current
																			// css
																			// top
																			// +
																			// distance
																			// dragged
																			// element
																			// has
																			// travelled
																			// vertically
							$(this).css('left', posLeftArray[i] + leftdiff); // Move
																				// element
																				// horizontally
																				// -
																				// current
																				// css
																				// left
																				// +
																				// distance
																				// dragged
																				// element
																				// has
																				// travelled
																				// horizontally
						}
					});					
					
				}
           }
       });
	
	}
   
   
};

/**
 * Use the below anonymous functions to 
 * Build some enum values so that we can use later
 */
(function (designComponent) {
	 
	designComponent.ComponentTypes =
	{TextBox:1,
			 ComboBox:2,
			 List:3,
			 Table:4,
			 Label:5,
			 TextArea:6,
			 HyperLink:7,
			 Button:8,
			 HeaderMenu:9,
			 LeftMenu:10,
			 Accordian:11,
			 TextReport:12};
 
}(SwiftUI.UIDesignComponent || {}));

/**
 * Text box component
 */
SwiftUI.TextBoxComponent = function(textBoxId) {
	  this.init(textBoxId);
};

SwiftUI.TextBoxComponent.prototype =  {

	init:function(textBoxId){
	      /**
			 * Assign default data loading services url
			 */
	      this.options = {  
	          text  : this.textBoxId,
	          name  : this.textBoxId,
	          id    : this.textBoxId,
	          icon  : "",
	          htmlElementText : "<input type='text' id='' name=''></input>",
	          componentType : SwiftUI.UIDesignComponent.ComponentTypes.TextBox
	      };
	      
	      SwiftUI.extend(this,new SwiftUI.UIDesignComponent(this.options));
	      
	}
};
// Create a democomponent so that
new SwiftUI.TextBoxComponent("SwiftUI_DemoComponent");




SwiftUI.includeLoaded('SwiftUIDesignComponent.js');